package com.tanhua.mongo.api;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.dubbo.api.UserLocationApi;
import com.tanhua.model.mongo.UserLocation;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: cl
 * @Date: 2022/5/10 - 05 - 10
 * @Description:
 */

/**
 * 用户地理位置服务
 */
@DubboService
public class UserLocationApiImpl implements UserLocationApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 上传或者更新用户地理位置(根据用户id)
     *
     * @param userId
     * @param longitude
     * @param latitude
     * @param addrStr
     * @return
     */
    @Override
    public boolean updateLocation(Long userId, Double longitude, Double latitude, String addrStr) {

        try {
            //1、查询判断地理位置信息是否存在
            Query query = Query.query(Criteria.where("userId").is(userId));
            UserLocation userLocation = mongoTemplate.findOne(query, UserLocation.class);

            if (userLocation == null) {
                //2、不存在创建用户地理位置信息
                userLocation = new UserLocation();
                userLocation.setUserId(userId);
                userLocation.setAddress(addrStr);//地址名称
                userLocation.setLocation(new GeoJsonPoint(longitude, latitude));//经纬度
                userLocation.setCreated(System.currentTimeMillis());
                userLocation.setUpdated(System.currentTimeMillis());
                userLocation.setLastUpdated(System.currentTimeMillis());
                mongoTemplate.save(userLocation);
            } else {
                //3、存在更新用户地理位置
                Update update = Update.update("location", new GeoJsonPoint(longitude, latitude))
                        .set("address", addrStr)
                        .set("updated", System.currentTimeMillis())
                        .set("lastUpdated", userLocation.getUpdated());
                mongoTemplate.updateFirst(query, update, UserLocation.class);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * 通过距离查询附近的用户
     *
     * @param distance
     * @return
     */
    @Override
    public List<Long> searchNearUser(Long userId, Double distance) {

        //1、获取当前用户的地理位置
        UserLocation userLocation = mongoTemplate.findOne(Query.query(Criteria.where("userId").is(userId)), UserLocation.class);
        if (userLocation == null) {
            return null;
        }
        //方式一：获取用户
//        //2、创建圆心
//        GeoJsonPoint point = userLocation.getLocation();
//        //3、创建半径
//        Distance distance1 = new Distance(distance / 1000, Metrics.KILOMETERS);//千米
//        //4、创建圆
//        Circle circle = new Circle(point,distance1);
//        //5、查询
//        Query query = Query.query(Criteria.where("location").withinSphere(circle));
//        List<UserLocation> list = mongoTemplate.find(query, UserLocation.class);
//
//        return CollUtil.getFieldValues(list, "userId", Long.class);

        //方式二：获取并获取距离信息
        //1、创建圆心
        GeoJsonPoint point = userLocation.getLocation();
        //2、构建NearQuery对象
        NearQuery nearQuery = NearQuery.near(point, Metrics.KILOMETERS)
                .maxDistance(distance / 1000, Metrics.KILOMETERS);
        //3、调用mongoTemplate的geoNear方法查询
        GeoResults<UserLocation> geoResults = mongoTemplate.geoNear(nearQuery, UserLocation.class);
        //4、解析GeoResult对象，获取距离和数据
        List<Long> ids = new ArrayList<>();
        for (GeoResult<UserLocation> geoResult : geoResults) {
            Long userId1 = geoResult.getContent().getUserId();
            ids.add(userId1);
        }
        return ids;
    }
}
